init('StringUtils');
/**
 * StringUtils.js
 * 
 * exports
 *  toHTML(obj, indent) : string
 *   - converts an object to an HTML string.
 *   
 *  trimQuote(string) : string
 *   - removes quotes and trims white space
 *     examples : "Testing "
 *                -> Testing
 *
 *  format(string, object...) : string
 *   - replaces items in the string with objects provided as arguments
 *     examples : "Name : ${name}", {name:"Sam"}    
 *                 -> "Name : Sam Axe"
 *              : "Name : ${0} ${1}", "Sam", "Axe"  
 *                 -> "Name : Sam Axe"
 *              : "Name : ${name.first} ${name.last}", {name:{first:"Sam", "Axe"}}
 *                 -> "Name : Sam Axe"
 */
(function(){
	var Collections = require('./Collections.js'),
	    ObjectUtils = require('./ObjectUtils.js');
	
	var iterate = Collections.iterate,
	       List = Collections.List;
	
	var trimQuote = function(value){
		if( !value ) return value;
		if( value.match(/^['"]/) ) value = value.substring(1);
		if( value.match(/['"]$/) ) value = value.substring(0, value.length-1);
		return value.trim();
	};
	
	var makeString = function(obj, indent, config){
		if( List.contains(config.values, obj) ) return '[Object object]';
		if( !obj ) return 'undefined';
		if( typeof obj === 'string' ) return config.stringWrapper(obj);
		if( typeof obj != 'object' ) return obj;
		config.values.push(obj);
		if( obj.length ){
			var out = '';
			var callee = arguments.callee;
			iterate(obj, function(element){
				if( out ) out += ',';
				else out += '['
				out += callee(element, indent, config);	
			})
			out += ']';
			return out;
		}
		if( !indent ) indent = '';
		var findent = indent + config.space;
		var out = '{' + config.newline;
		var lead = '';
		for(property in obj){
			if(!config.includePrivate && property.match(/^__.*/) ){
				continue;
			}
			out += findent + lead + property + ' : ' + arguments.callee(obj[property], findent, config) + config.newline;
			lead = ','
		}
		out += indent + '}';
		return '' + out;
	}
	
	var toEditable = function(obj){
		return makeString(obj, '', {
			newline : '\n'
			,space  : '   '
			,stringWrapper : function(value){
				return "'" + value + "'";
			}
			,values : []
		});
	};
	
	var toHTML = function(obj, indent){
		return makeString(obj, indent, {
			newline : '<br/>'
			,space  : '&nbsp;&nbsp;&nbsp;'
			,stringWrapper : function(value){
				return "'<span>" + value + "</span>'";
			}
		});
	};
	
	var format = function(message){
		var result = message;
		var variables = message.match(/[$]{[a-zA-Z0-9\[\]\.$_]*}/g)
		var incoming = arguments;
		iterate(variables, function(variable){
			var name = variable.substring(2, variable.length-1);
			if( name.match(/^[0-9]*$/) ){
				var i = parseInt(name);
				result = result.replace(variable, trimQuote(toHTML(incoming[i+1])));
			}
			else{
				var value = 'undefined';
				try{
					value = ObjectUtils.get(name).from(incoming[1]);
					var tmp = JSON.stringify(value);
					tmp = trimQuote(tmp || value);
					result = result.replace(variable, tmp);
				}catch(e){
					if( e.type == 'circular_structure' ){
						//console.log(value);
						try{ result = result.replace(variable, value); } catch(ignore){}
					}else{
						console.log(e);
					}
				}
			}
		});
		return result;
	};
	var formatEach = function(collection, formatString, separator){
		var results = [];
		var _sep = '';
		iterate(collection, function(item){
			results.push(_sep + format(formatString, item) );
			if( !_sep && separator ) _sep = separator;
		});
		return results;
	};
	var fit = function(value, length, filler){
		if(!value)return;
		filler = filler || ' ';
		if(value.length > length){
			value = value.substring(0, length);
		}
		while(value.length < length)
			value = value + filler;
		return value;
	};
	exports.fit        = fit;
	exports.formatEach = formatEach;
	exports.format     = format;
	exports.trimQuote  = trimQuote;
	exports.toHTML     = toHTML;
	exports.toEditable = toEditable;
})();